import os
import sys
import time
import logging
import yaml

exe_path = os.path.dirname(os.path.abspath(sys.argv[0]))
os.environ['PATH'] += os.pathsep + os.path.join(exe_path, 'Graphviz', 'bin')
sys.path.append(exe_path)

from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal, QTimer
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtWidgets import *
from transitions.extensions import HierarchicalGraphMachine as Machine

LOG = logging.getLogger()


class Model:
    def show_graph(self, name):
        path = os.path.join(exe_path, 'svg_temp', '{}'.format(name))
        self.get_graph().draw(path, prog='dot', format='svg')


class UpdateSvgPicture(QTabWidget):
    SVG_Changed = pyqtSignal()
    Picture_Changed = pyqtSignal()

    def __init__(self):
        super(UpdateSvgPicture, self).__init__()
        self.resize(1000, 618)
        self.check_file_time = 0.5
        self.svg_picture_time = 0
        self.other_picture_time = 0
        self.setWindowTitle("动态更新图片")
        self.setWindowIcon(QIcon('update_fsm.ico'))
        self.history_record = QTextEdit()
        self.history_record.append('python的transtions库开源地址:https://github.com/pytransitions/transitions')
        self.history_record.append('状态机示例:https://github.com/pytransitions/transitions/tree/master/examples')
        self.history_record.append(
            '本程序代码开源地址:https://gitee.com/m986883511/py-qt5-journey/tree/master/%E5%8A%A8%E6%80%81%E6%9B%B4%E6%96%B0%E5%9B%BE%E7%89%87')
        self.svg_tab = QWidget()
        self.set_svg_tab()
        self.addTab(self.svg_tab, '矢量图片')

        self.picture_tab = QWidget()
        self.set_picture_tab()
        self.addTab(self.picture_tab, '非矢量图片')

        self.yaml_tab = QWidget()
        self.set_yaml_table()
        self.addTab(self.yaml_tab, '解析yaml成矢量图片')

        self.other_tab = QWidget()
        self.set_other_tab()
        self.addTab(self.other_tab, '操作历史')
        self.svg_path = None
        self.SVG_Changed.connect(self.load_svg)

        self.update_svg_timer = QTimer(self)
        self.update_svg_timer.timeout.connect(self.update_svg)
        self.update_svg_timer.setInterval(int(self.check_file_time * 1000))
        self.picture_path = None
        self.update_picture_timer = QTimer(self)
        self.update_picture_timer.timeout.connect(self.update_other_picture)
        self.update_picture_timer.setInterval(int(self.check_file_time * 1000))
        self.Picture_Changed.connect(self.load_other_picture)
        self.mkdir_svg_temp_dir()

    def mkdir_svg_temp_dir(self):
        path = os.path.join(exe_path, 'svg_temp')
        if not os.path.exists(path):
            os.mkdir(path)

    def update_svg(self):
        if self.svg_path and os.path.exists(self.svg_path):
            update_time = os.path.getatime(self.svg_path)
            if update_time != self.svg_picture_time:
                self.history_record.append('检测到矢量图片更新:{}'.format(self.svg_path))
                self.svg_picture_time = update_time
                self.SVG_Changed.emit()

    def update_other_picture(self):
        if self.picture_path and os.path.exists(self.picture_path):
            update_time = os.path.getatime(self.picture_path)
            if update_time != self.other_picture_time:
                self.history_record.append('检测到非矢量图片更新:{}'.format(self.picture_path))
                self.other_picture_time = update_time
                self.Picture_Changed.emit()

    def set_other_tab(self):
        layout = QVBoxLayout()
        # spaceItem = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.set_interval_button = QPushButton('修改检测图片更新间隔时间', self)
        self.history_record.append('此页显示操作历史，检测图片更新响应时间为{:.1f}秒'.format(self.check_file_time))
        self.set_interval_button.clicked.connect(self.set_check_file_time)
        layout.addWidget(self.set_interval_button)
        # layout.addSpacerItem(spaceItem)
        layout.addWidget(self.history_record)
        self.other_tab.setLayout(layout)

    def set_check_file_time(self):
        if self.check_file_time == 0.5:
            self.check_file_time = 1
        elif self.check_file_time == 1:
            self.check_file_time = 3
        elif self.check_file_time == 3:
            self.check_file_time = 0.5
        self.update_picture_timer.setInterval(int(self.check_file_time * 1000))
        self.update_svg_timer.setInterval(int(self.check_file_time * 1000))
        if self.update_picture_timer.isActive():
            self.update_picture_timer.stop()
            self.update_picture_timer.start()
        if self.update_svg_timer.isActive():
            self.update_svg_timer.stop()
            self.update_svg_timer.start()
        self.set_interval_button.setText('切换检测图片更新间隔时间={:.1f}秒'.format(self.check_file_time))
        self.history_record.append('检测间隔更改为{:.1f}秒'.format(self.check_file_time))

    def set_picture_tab(self):
        layout = QVBoxLayout()
        btn = QPushButton(self)
        btn.setText("打开非矢量图片(自动更新)")
        btn.clicked.connect(self.open_other_img)
        self.picture_label = QLabel()
        self.picture_label.setScaledContents(True)
        layout.addWidget(btn)
        layout.addWidget(self.picture_label)
        self.picture_tab.setLayout(layout)

    def set_svg_tab(self):
        layout = QVBoxLayout()
        btn = QPushButton(self)
        btn.setText("打开SVG矢量图片(自动更新)")
        btn.clicked.connect(self.open_svg_img)
        self.svgwidget = QSvgWidget()
        layout.addWidget(btn)
        layout.addWidget(self.svgwidget)
        self.svg_tab.setLayout(layout)

    def set_yaml_table(self):
        layout = QVBoxLayout()
        btn = QPushButton(self)
        btn.setText("打开transtion的yaml状态迁移配置文件")
        btn.clicked.connect(self.generate_yaml_svg)
        self.yaml_svgwidget = QSvgWidget()
        layout.addWidget(btn)
        layout.addWidget(self.yaml_svgwidget)
        self.yaml_tab.setLayout(layout)

    def generate_yaml_svg(self):
        self.history_record.append('点击:打开yaml状态机脚本')
        imgName, imgType = QFileDialog.getOpenFileName(self, "打开yaml状态机脚本", "", "*.yaml")
        if not imgName:
            return
        try:
            self.history_record.append('选中了{}'.format(imgName))
            config = self.read_yaml(imgName)
            model = Model()
            config['model'] = model
            machine = Machine(**config)
            basename = os.path.splitext(os.path.basename(imgName))[0]
            model.show_graph(basename)
            svg_path = os.path.join(exe_path, 'svg_temp', '{}.svg'.format(basename))
            self.history_record.append('生成了{}'.format(svg_path))
            self.yaml_svgwidget.load(svg_path)
        except Exception as e:
            err_msg = '解析yaml生成svg图片错误，你的yaml脚本可能不是状态机配置脚本!\n\n错误信息:{}'.format(str(e))
            self.history_record.append(err_msg)
            self.show_message(err_msg)

    def show_message(self, err_msg):
        QtWidgets.QMessageBox.warning(self, "错误", err_msg, QtWidgets.QMessageBox.Cancel)

    def open_svg_img(self):
        try:
            self.history_record.append('点击:打开矢量svg图片')
            imgName, imgType = QFileDialog.getOpenFileName(self, "打开矢量svg图片", "", "*svg")
            self.svg_path = imgName
            self.load_svg()
        except Exception as e:
            err_msg = '加载矢量图片失败，file:{}, error={}'.format(imgName, str(e))
            self.history_record.append(err_msg)
            self.history_record.append('更新矢量图片定时器关闭')
            self.update_svg_timer.stop()
            self.show_message(err_msg)
        else:
            if imgName:
                self.update_svg_timer.start()
                self.history_record.append('更新矢量图片定时器启动')

    def read_yaml(self, path):
        try:
            with open(path, 'r', encoding='utf-8') as f:
                result = f.read()
            yaml_dict = yaml.safe_load(result)
            return yaml_dict
        except Exception as e:
            err_msg = 'read {} failed, error={}'.format(path, e)
            LOG.warning(err_msg)
            self.history_record.append('读取{}报错'.format(err_msg))
            raise Exception(err_msg)

    def load_svg(self):
        if self.svg_path:
            self.history_record.append('加载了{}'.format(self.svg_path))
            self.svgwidget.load(self.svg_path)

    def open_other_img(self):
        try:
            imgName, imgType = QFileDialog.getOpenFileName(self, "打开非矢量图片", "", "*png;*.bmp;*.jpg;*.jpeg")
            self.picture_path = imgName
            self.load_other_picture()
        except Exception as e:
            err_msg = '加载非矢量图片失败，file:{}, error={}'.format(imgName, str(e))
            self.history_record.append(err_msg)
            self.history_record.append('更新非矢量图片定时器关闭')
            self.update_picture_timer.stop()
            self.show_message(err_msg)
        else:
            if imgName:
                self.update_picture_timer.start()
                self.history_record.append('更新非矢量图片定时器启动')

    def load_other_picture(self):
        if self.picture_path:
            print('load_other_picture', self.picture_path)
            pix = QPixmap(self.picture_path)
            self.picture_label.setPixmap(pix)


if __name__ == "__main__":
    import cgitb

    cgitb.enable()
    app = QtWidgets.QApplication(sys.argv)
    my = UpdateSvgPicture()
    my.show()
    sys.exit(app.exec_())
